package com.haiya.common.domain.model;

import com.haiya.common.AssertionConcern;

import java.io.Serializable;

/**
 * @author qiaoguoqiang
 * 抽象Id类:
 * 1. hashCode(): 提供基本的hashCode实现，具体由两个hashOddValue()和hashPrimeValue()来决定。
 *      这两个方法是抽象方法，由具体子类来实现。
 * 2. validateId(): 抽象方法，验证ID有效性，可以由子类来实现。如果ID无效抛出运行时异常
 */
public abstract class AbstractId
        extends AssertionConcern
        implements Identity, Serializable {

    private static final long serialVersionUID = 1L;

    private String id;

    @Override
    public String id() {
        return this.id;
    }

    @Override
    public boolean equals(Object anObject) {
        boolean equalObjects = false;

        if (anObject != null && this.getClass() == anObject.getClass()) {
            AbstractId typedObject = (AbstractId) anObject;
            equalObjects = this.id().equals(typedObject.id());
        }

        return equalObjects;
    }

    @Override
    public int hashCode() {
        int hashCodeValue =
                +(this.hashOddValue() * this.hashPrimeValue())
                        + this.id().hashCode();

        return hashCodeValue;
    }

    @Override
    public String toString() {
        return this.getClass().getSimpleName() + " [id=" + id + "]";
    }

    protected AbstractId(String anId) {
        this();

        this.setId(anId);
    }

    protected AbstractId() {
        super();
    }

    protected abstract int hashOddValue();

    protected abstract int hashPrimeValue();

    protected void validateId(String anId) {
        // implemented by subclasses for validation.
        // throws a runtime exception if invalid.
    }

    private void setId(String anId) {
        this.assertArgumentNotEmpty(anId, "The basic identity is required.");
        this.assertArgumentLength(anId, 36, "The basic identity must be 36 characters.");

        this.validateId(anId);

        this.id = anId;
    }
}
